package dao;

import entity.User;
import org.apache.commons.codec.digest.DigestUtils;
import utils.ArgsList;
import utils.JDBCConnection;
import utils.JDBCFactory;

import java.math.BigInteger;
import java.sql.SQLException;
import java.util.List;
import utils.Common;

public class UserDAOImp implements UserDAO {

    /**
     * 向数据库注册一个用户
     * @param uname 用户名
     * @param upass 口令
     * @param unick 昵称
     * @return 新注册的用户实体，注册失败返回null
     */
    @Override
    public User register(String uname, String unick, String upass) {
        if(Common.isStringEmpty(uname) || Common.isStringEmpty(upass)) return null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            BigInteger id;
            long defaultScore = top.RuntimeContextProvider.getContextProvider().getRule().getNewPlayerInitPoints();
            if(Common.isStringEmpty(unick)) {
                id = (BigInteger) conn.updateForGeneratedKey(
                        "insert into users_t(`name`, `passwordHash`, `win`, `lost`, `run`, `score`, `joinRank`)" +
                                " values(?, ?, 0, 0, 0, ?, 0)",
                        uname, upass, defaultScore
                );
            } else {
                id = (BigInteger) conn.updateForGeneratedKey(
                        "insert into users_t(`name`, `nick`, `passwordHash`, `win`, `lost`, `run`, `score`, `joinRank`)" +
                                " values(?, ?, ?, 0, 0, 0, ?, 0)",
                        uname, unick, upass, defaultScore
                );
            }
            JDBCFactory.returnBack(conn);
            if(id != null) {
                return new User(id.longValue(), uname, unick, upass, null, 0, 0, 0, defaultScore, 0, "启用");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public User query(long uid) {
        List<User> l = null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            l = conn.queryEntities(User.class,
            "select " +
                    "`id`, `name`, `nick`, `passwordHash`, " +
                    "`headPic`, `win`, `lost`, `run`, " +
                    "`score`, `joinRank`, `state` " +
                "from users_t where id = ?",
            uid);
            JDBCFactory.returnBack(conn);
            if(l != null  &&  l.size() > 0) {
                return l.get(0);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public User query(String uname) {
        if(Common.isStringEmpty(uname)) return null;
        List<User> l = null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            l = conn.queryEntities(User.class,
            "select " +
                    "`id`, `name`, `nick`, `passwordHash`, " +
                    "`headPic`, `win`, `lost`, `run`, " +
                    "`score`, `joinRank`, `state` " +
                "from users_t where name = ?",
            uname);
            JDBCFactory.returnBack(conn);
            if(l != null  &&  l.size() > 0) {
                return l.get(0);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<User> queryByNick(String unick) {
        List<User> l = null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            l = conn.queryEntities(User.class,
            "select " +
                    "`id`, `name`, `nick`, `passwordHash`, " +
                    "`headPic`, `win`, `lost`, `run`, " +
                    "`score`, `joinRank`, `state` " +
                    "from users_t where nick = ?", unick
            );
            JDBCFactory.returnBack(conn);
            return l;
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<User> getAllRankedUsers() {
        List<User> l = null;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            l = conn.queryEntities(User.class,
            "select " +
                    "`id`, `name`, `nick`, `passwordHash`, " +
                    "`headPic`, `win`, `lost`, `run`, " +
                    "`score`, `joinRank`, `state` " +
                    "from users_t where joinRank = 1"
            );
            JDBCFactory.returnBack(conn);
            return l;
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public boolean unregister(long uid) {
        //delete from t_qq where qq_id = ?
        int updated = 0;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            updated = conn.update("delete from users_t where id = ?", uid);
            JDBCFactory.returnBack(conn);
            return updated > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public boolean unregister(String name) {
        //delete from t_qq where qq_id = ?
        if(Common.isStringEmpty(name)) return false;
        int updated = 0;
        try {
            JDBCConnection conn = JDBCFactory.takeJDBC();
            updated = conn.update("delete from users_t where name = ?", name);
            JDBCFactory.returnBack(conn);
            return updated > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    /*
    private Long    id;
    private String  name;
    private String  nick;
    private String  passwordHash;
    private String  headPic;

    private Integer win;
    private Integer lost;
    private Integer run;
    private Long    score;*/
    //update t_qq set qq_id = ? where u_id = ?
    @Override
    public boolean update(Long uid, String name, User newData) {

        if(uid == null && Common.isStringEmpty(name)) return false;

        StringBuilder sqlColumns  = new StringBuilder();
        ArgsList<Object> argsList = new ArgsList<>();

        String searchCondition = (uid == null? " where name = ?": " where id = ?");

        boolean firstArg = true;

        String  tmp;
        Integer tmpI;
        Long    tmpL;

        if(!Common.isStringEmpty(tmp = newData.getName())) {
            sqlColumns.append(" name = ?");
            argsList.add(tmp);
            firstArg = false;
        }

        if(!Common.isStringEmpty(tmp = newData.getNick())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" nick = ?");
            argsList.add(tmp);
            firstArg = false;
        }

        if(!Common.isStringEmpty(tmp = newData.getPasswordHash())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" passwordHash = ?");
            argsList.add(tmp);
            firstArg = false;
        }

        if(!Common.isStringEmpty(tmp = newData.getHeadPic())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" headPic = ?");
            argsList.add(tmp);
            firstArg = false;
        }

        if(null != (tmpI = newData.getWin())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" win = ?");
            argsList.add(tmpI);
            firstArg = false;
        }

        if(null != (tmpI = newData.getLost())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" lost = ?");
            argsList.add(tmpI);
            firstArg = false;
        }

        if(null != (tmpI = newData.getRun())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" run = ?");
            argsList.add(tmpI);
            firstArg = false;
        }

        if(null != (tmpL = newData.getScore())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" score = ?");
            argsList.add(tmpL);
            firstArg = false;
        }

        if(null != (tmpI = newData.getJoinRank())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" joinRank = ?");
            argsList.add(tmpI);
            firstArg = false;
        }

        if(!Common.isStringEmpty(tmp = newData.getState())) {
            if(!firstArg) sqlColumns.append(',');
            sqlColumns.append(" state = ?");
            argsList.add(tmp);
        }

        argsList.add(uid == null? name: uid);

        int updated = 0;
        try {
            //System.out.println("update users_t set" + sqlColumns.toString() + searchCondition);
            //System.out.println(argsList);
            JDBCConnection conn = JDBCFactory.takeJDBC();
            updated = conn.update(argsList, "update users_t set" + sqlColumns.toString() + searchCondition);
            JDBCFactory.returnBack(conn);
            return updated > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static void main(String[] args) {
        UserDAO userDAO = new UserDAOImp();
        String psw = DigestUtils.md5Hex(DigestUtils.sha256Hex("comcomlyz"));
        System.out.println(userDAO.register("baijin0729", "白槿", psw));
        System.out.println(userDAO.register("Zafkiel", "兰兰", psw));
    }
}